"""
https://blog.csdn.net/weixin_39122088/article/details/106938800

【tensorflow2.0】26.tf2.0实现InceptionV3
"""

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import warnings

warnings.filterwarnings('ignore')
import tensorflow as tf

tf.compat.v1.logging.set_verbosity(40)

from tensorflow.keras import layers, models, Sequential, optimizers, losses
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, BatchNormalization, Activation, AveragePooling2D, GlobalAveragePooling2D
# from tensorflow.keras.models import Sequential
# from tensorflow.keras import utils

# (x_train,y_train),(x_test,y_test)=tf.keras.datasets.cifar10.load_data()
# x_train=x_train.reshape([-1,32,32,3])/255
# x_test=x_test.reshape([-1,32,32,3])/255


#因为每一个卷积层都带有批标准化和激活函数relu，所以这里我们用函数将他们合并在一起
def conv2d(x,
        filters,
        num_row,
        num_col,
        padding='same',
        strides=(1, 1),
        name=None):
    x = Conv2D(
        filters, (num_row, num_col),
        strides=strides,
        padding=padding,
        use_bias=False)(x)
    x = BatchNormalization(scale=False)(x)
    x = Activation('relu')(x)
    return x
#首先对输入数据进行处理
inputs = tf.keras.Input([229,229,3])
# x = conv2d(inputs,32,3,3,strides=(2,2),padding='valid')# out:（227，227，32）  # ATTENTION 我怀疑这里strides为(1, 1)
x = conv2d(inputs,32,3,3,strides=(1,1),padding='valid')# out:（227，227，32）  # ATTENTION 我怀疑这里strides为(1, 1)
x = conv2d(x, 32, 3, 3, padding='valid')# out:（225，225，32）
x = conv2d(x, 64, 3, 3)# out:（225，225，64）
x = MaxPooling2D((3,3),strides=(2,2))(x)# out:（112，112，64）

x = conv2d(x, 80, 3, 3, padding='valid')# out:（110，110，80）
x = conv2d(x, 192, 3, 3, padding='valid')# out:（108，108，192）
x = MaxPooling2D((3, 3), strides=(2, 2))(x)# out:（54，54，192）

#这里我们要进行三次 第一次：  out:（53，53，256）
#分支一
branch_1 = conv2d(x,64,1,1)
#分支二
branch_2 = conv2d(x,48,1,1)
branch_2 = conv2d(branch_2,64,5,5)
#分支三
branch_3 = conv2d(x,64,1,1)
branch_3 = conv2d(branch_3,96,3,3)
branch_3 = conv2d(branch_3,96,3,3)
#分支四
branch_4 = AveragePooling2D((3,3),strides=(1,1),padding='same')(x)
branch_4 = conv2d(branch_4,32,1,1)
#将四个分支叠加在一起，共64+64+96+32=256
x = tf.keras.layers.concatenate([branch_1,branch_2,branch_3,branch_4],axis=3)

#第二次  out(53,53,288)
branch_1 = conv2d(x,64,1,1)

branch_2 = conv2d(x,48,1,1)
branch_2 = conv2d(branch_2,64,5,5)

branch_3 = conv2d(x,64,1,1)
branch_3 = conv2d(branch_3,96,3,3)
branch_3 = conv2d(branch_3,96,3,3)

branch_4 = AveragePooling2D((3,3),strides=(1,1),padding='same')(x)
branch_4 = conv2d(branch_4,64,1,1)

x = tf.keras.layers.concatenate([branch_1,branch_2,branch_3,branch_4],axis=3)

#第三次 out：(53，53，288)
branch_1 = conv2d(x,64,1,1)

branch_2 = conv2d(x,48,1,1)
branch_2 = conv2d(branch_2,64,5,5)

branch_3 = conv2d(x,64,1,1)
branch_3 = conv2d(branch_3,96,3,3)
branch_3 = conv2d(branch_3,96,3,3)

branch_4 = AveragePooling2D((3,3),strides=(1,1),padding='same')(x)
branch_4 = conv2d(branch_4,64,1,1)

x = tf.keras.layers.concatenate([branch_1,branch_2,branch_3,branch_4],axis=3)


#第二部分 1
branch_1 = conv2d(x, 384, 3, 3, strides=(2, 2), padding='valid')

branch_2 = conv2d(x, 64, 1, 1)
branch_2 = conv2d(branch_2, 96, 3, 3)
branch_2 = conv2d(branch_2, 96, 3, 3, strides=(2, 2), padding='valid')

branch_3 = MaxPooling2D((3, 3), strides=(2, 2))(x)
x = layers.concatenate(
        [branch_1, branch_2, branch_3], axis=3)

#2
branch_1 = conv2d(x, 192, 1, 1)

branch_2 = conv2d(x, 128, 1, 1)
branch_2 = conv2d(branch_2, 128, 1, 7)
branch_2 = conv2d(branch_2, 192, 7, 1)

branch_3 = conv2d(x, 128, 1, 1)
branch_3 = conv2d(branch_3, 128, 7, 1)
branch_3 = conv2d(branch_3, 128, 1, 7)
branch_3 = conv2d(branch_3, 128, 7, 1)
branch_3 = conv2d(branch_3, 192, 1, 7)

branch_4 = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)
branch_4 = conv2d(branch_4, 192, 1, 1)
x = layers.concatenate(
    [branch_1, branch_2, branch_3, branch_4],
    axis=3,
    )

#3、4
for i in range(2):
    branch_1 = conv2d(x, 192, 1, 1)

    branch_2 = conv2d(x, 160, 1, 1)
    branch_2 = conv2d(branch_2, 160, 1, 7)
    branch_2 = conv2d(branch_2, 192, 7, 1)

    branch_3 = conv2d(x, 160, 1, 1)
    branch_3 = conv2d(branch_3, 160, 7, 1)
    branch_3 = conv2d(branch_3, 160, 1, 7)
    branch_3 = conv2d(branch_3, 160, 7, 1)
    branch_3 = conv2d(branch_3, 192, 1, 7)

    branch_4 = AveragePooling2D(
        (3, 3), strides=(1, 1), padding='same')(x)
    branch_4 = conv2d(branch_4, 192, 1, 1)

    x = layers.concatenate(
        [branch_1, branch_2, branch_3, branch_4],
        axis=3,
        )

#5
branch_1 = conv2d(x, 192, 1, 1)

branch_2 = conv2d(x, 192, 1, 1)
branch_2 = conv2d(branch_2, 192, 1, 7)
branch_2 = conv2d(branch_2, 192, 7, 1)

branch_3 = conv2d(x, 192, 1, 1)
branch_3 = conv2d(branch_3, 192, 7, 1)
branch_3 = conv2d(branch_3, 192, 1, 7)
branch_3 = conv2d(branch_3, 192, 7, 1)
branch_3 = conv2d(branch_3, 192, 1, 7)

branch_4 = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)
branch_4 = conv2d(branch_4, 192, 1, 1)
x = layers.concatenate(
    [branch_1, branch_2, branch_3, branch_4],
    axis=3,
    )

#第三部分
branch_1 = conv2d(x, 192, 1, 1)
branch_1 = conv2d(branch_1, 320, 3, 3,strides=(2, 2), padding='valid')

branch_2 = conv2d(x, 192, 1, 1)
branch_2 = conv2d(branch_2, 192, 1, 7)
branch_2 = conv2d(branch_2, 192, 7, 1)
branch_2 = conv2d(branch_2, 192, 3, 3, strides=(2, 2), padding='valid')

branch_pool = MaxPooling2D((3, 3), strides=(2, 2))(x)
x = layers.concatenate(
    [branch_1, branch_2, branch_pool], axis=3)


branch3x3 = conv2d(x, 192, 1, 1)
branch3x3 = conv2d(branch3x3, 320, 3, 3,strides=(2, 2), padding='valid')

branch7x7x3 = conv2d(x, 192, 1, 1)
branch7x7x3 = conv2d(branch7x7x3, 192, 1, 7)
branch7x7x3 = conv2d(branch7x7x3, 192, 7, 1)
branch7x7x3 = conv2d(branch7x7x3, 192, 3, 3, strides=(2, 2), padding='valid')

branch_pool = MaxPooling2D((3, 3), strides=(2, 2))(x)
x = layers.concatenate(
    [branch3x3, branch7x7x3, branch_pool], axis=3)


for i in range(2):
    branch1x1 = conv2d(x, 320, 1, 1)

    branch3x3 = conv2d(x, 384, 1, 1)
    branch3x3_1 = conv2d(branch3x3, 384, 1, 3)
    branch3x3_2 = conv2d(branch3x3, 384, 3, 1)
    branch3x3 = layers.concatenate(
        [branch3x3_1, branch3x3_2], axis=3)

    branch3x3dbl = conv2d(x, 448, 1, 1)
    branch3x3dbl = conv2d(branch3x3dbl, 384, 3, 3)
    branch3x3dbl_1 = conv2d(branch3x3dbl, 384, 1, 3)
    branch3x3dbl_2 = conv2d(branch3x3dbl, 384, 3, 1)
    branch3x3dbl = layers.concatenate(
        [branch3x3dbl_1, branch3x3dbl_2], axis=3)

    branch_pool = AveragePooling2D(
        (3, 3), strides=(1, 1), padding='same')(x)
    branch_pool = conv2d(branch_pool, 192, 1, 1)
    x = layers.concatenate(
        [branch1x1, branch3x3, branch3x3dbl, branch_pool],
        axis=3,
        )
# 平均池化后全连接。
x = GlobalAveragePooling2D(name='avg_pool')(x)
x = Dense(1000, activation='softmax', name='predictions')(x)

model = tf.keras.Model(inputs,x)

model.summary()

